package com.nulldev.util.uri.yt;

public class Format {
    public enum VCodec {
        H263("h263"), H264("h264"), MPEG4("mp4"), VP8("vp8"), VP9("vp9"), NONE("none"), AV1("av1")
        
        ;
    	
    	private final String disp;
    	private VCodec(final String display) {
    		this.disp = display;
    	}
    	
    	@Override
    	public String toString() {
    		return this.disp;
    	}
    }

    public enum ACodec {
        MP3("mp3"), AAC("aac"), VORBIS("vorbis"), OPUS("opus"), NONE("none")
        
        ;
        
    	private final String disp;
    	private ACodec(final String display) {
    		this.disp = display;
    	}
    	
    	@Override
    	public String toString() {
    		return this.disp;
    	}
    }

    private int itag;
    private String ext;
    private int height;
    private int fps;
    private VCodec vCodec;
    private ACodec aCodec;
    private int audioBitrate;
    private boolean isDashContainer;
    private boolean isHlsContent;
    
    private final boolean is10bitcolour;

    Format(int itag, String ext, int height, VCodec vCodec, ACodec aCodec, boolean isDashContainer) {
        this.itag = itag;
        this.ext = ext;
        this.height = height;
        this.fps = 30;
        this.audioBitrate = -1;
        this.isDashContainer = isDashContainer;
        this.isHlsContent = false;
        this.vCodec = vCodec;
        this.aCodec = aCodec;
        this.is10bitcolour = false;
    }

    Format(int itag, String ext, VCodec vCodec, ACodec aCodec, int audioBitrate, boolean isDashContainer) {
        this.itag = itag;
        this.ext = ext;
        this.height = -1;
        this.fps = 30;
        this.audioBitrate = audioBitrate;
        this.isDashContainer = isDashContainer;
        this.isHlsContent = false;
        this.vCodec = vCodec;
        this.aCodec = aCodec;
        this.is10bitcolour = false;
    }

    Format(int itag, String ext, int height, VCodec vCodec, ACodec aCodec, int audioBitrate,
           boolean isDashContainer) {
        this.itag = itag;
        this.ext = ext;
        this.height = height;
        this.fps = 30;
        this.audioBitrate = audioBitrate;
        this.isDashContainer = isDashContainer;
        this.isHlsContent = false;
        this.vCodec = vCodec;
        this.aCodec = aCodec;
        this.is10bitcolour = false;
    }

    Format(int itag, String ext, int height, VCodec vCodec, ACodec aCodec, int audioBitrate,
           boolean isDashContainer, boolean isHlsContent) {
        this.itag = itag;
        this.ext = ext;
        this.height = height;
        this.fps = 30;
        this.audioBitrate = audioBitrate;
        this.isDashContainer = isDashContainer;
        this.isHlsContent = isHlsContent;
        this.vCodec = vCodec;
        this.aCodec = aCodec;
        this.is10bitcolour = false;
    }

    Format(int itag, String ext, int height, VCodec vCodec, int fps, ACodec aCodec, boolean isDashContainer) {
    	this(itag, ext, height, vCodec, fps, aCodec, isDashContainer, false);
    }
    
    Format(int itag, String ext, int height, VCodec vCodec, int fps, ACodec aCodec, int bitrate, boolean isDashContainer,
    		final boolean is10bit) {
    	this(itag, ext, height, vCodec, fps, aCodec, bitrate, isDashContainer, is10bit, false);
    }
    
    Format(int itag, String ext, int height, VCodec vCodec, int fps, ACodec aCodec, boolean isDashContainer, final boolean is10bit) {
        this.itag = itag;
        this.ext = ext;
        this.height = height;
        this.audioBitrate = -1;
        this.fps = fps;
        this.isDashContainer = isDashContainer;
        this.isHlsContent = false;
        this.vCodec = vCodec;
        this.aCodec = aCodec;
        this.is10bitcolour = is10bit;
    }
    
    Format(int itag, String ext, int height, VCodec vCodec, int fps, ACodec aCodec, final int bitrate, boolean isDashContainer, 
    		final boolean is10bit, final boolean isHLS) {
        this.itag = itag;
        this.ext = ext;
        this.height = height;
        this.audioBitrate = bitrate;
        this.fps = fps;
        this.isDashContainer = isDashContainer;
        this.isHlsContent = isHLS;
        this.vCodec = vCodec;
        this.aCodec = aCodec;
        this.is10bitcolour = is10bit;
    }

    /**
     * Get the frames per second
     */
    @Deprecated
    public int getFps() {
        return fps;
    }

    /**
     * Audio bitrate in kbit/s or -1 if there is no audio track.
     */
    public int getAudioBitrate() {
        return audioBitrate;
    }

    /**
     * An identifier used by youtube for different formats.
     */
    public int getItag() {
        return itag;
    }

    /**
     * The file extension and conainer format like "mp4"
     */
    public String getExt() {
        return ext;
    }

    public boolean isDashContainer() {
        return isDashContainer;
    }

    public ACodec getAudioCodec() {
        return aCodec;
    }

    public VCodec getVideoCodec() {
        return vCodec;
    }

    public boolean isHlsContent() {
        return isHlsContent;
    }

    /**
     * The pixel height of the video stream or -1 for audio files.
     */
    public int getHeight() {
        return height;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Format format = (Format) o;

        if (itag != format.itag) return false;
        if (height != format.height) return false;
        if (fps != format.fps) return false;
        if (audioBitrate != format.audioBitrate) return false;
        if (isDashContainer != format.isDashContainer) return false;
        if (isHlsContent != format.isHlsContent) return false;
        if (ext != null ? !ext.equals(format.ext) : format.ext != null) return false;
        if (vCodec != format.vCodec) return false;
        return aCodec == format.aCodec;

    }

    @Override
    public int hashCode() {
        int result = itag;
        result = 31 * result + (ext != null ? ext.hashCode() : 0);
        result = 31 * result + height;
        result = 31 * result + fps;
        result = 31 * result + (vCodec != null ? vCodec.hashCode() : 0);
        result = 31 * result + (aCodec != null ? aCodec.hashCode() : 0);
        result = 31 * result + audioBitrate;
        result = 31 * result + (isDashContainer ? 1 : 0);
        result = 31 * result + (isHlsContent ? 1 : 0);
        result = 31 * result + (is10bitcolour ? 1 : 0);
        return result;
    }

    @Override
    public String toString() {
        return "Format{" +
                "itag=" + itag +
                ", ext='" + ext + '\'' +
                ", height=" + height +
                ", fps=" + fps +
                ", vCodec=" + vCodec +
                ", aCodec=" + aCodec +
                ", audioBitrate=" + audioBitrate +
                ", isDashContainer=" + isDashContainer +
                ", isHlsContent=" + isHlsContent +
                ", is10bit=" + is10bitcolour +
                '}';
    }

    /**
     * Returns the frames per second
     */
	public int getFPS() {
		return this.fps;
	}
	
	public boolean is10bit() {
		return this.is10bitcolour;
	}
}
